const path = require('path')
const fs = require('fs')

const { koaBody } = require('koa-body')
const { checkDirExist } = require('../utils/uploadFileHandler')
const { getDistance } = require('../utils/getDistance')
const {
    getActInfo,
    getACtDetailById
} = require('../service/activity.service')

const {
    getActLoaction
} = require('../service/actLocation.service')

const {
    getActSignScoreListByActId
} = require('../service/actSignScore.service')

const { formatDate } = require('../utils/formatData')

const {
    getChuangxinList,
    getXueyeList,
    getSixiangList,
    getWentiList,
} = require('../service/actScore.service')

const {
    insufficientPermissionsError,
    formateError,
    actapprovedError
} = require('../constant/err.type')
const { log } = require('console')


/**
 * 判断actId是否存在
 */
async function actIdIsExist (ctx, next) {
    try {
        const { actId } = Object.keys(ctx.query).length !== 0 ? ctx.query : ctx.request.body
        if (!actId) {
            console.error('缺少角色编码', ctx.request.body)
            ctx.app.emit('error', formateError, ctx)
            return
        }
    } catch (error) {
        console.error('缺少角色编码', error)
        ctx.app.emit('error', formateError, ctx)
        return
    }
    await next()
}

/**
 * 判断用户权限
 */
async function judgeCreateUserPwoer (ctx, next) {
    const { role } = ctx.state.token
    if (role !== 'super_admin' && role !== 'admin' && role !== 'act_organizer') {
        console.error('用户权限不足', role)
        ctx.app.emit('error', insufficientPermissionsError, ctx)
        return
    }
    await next()
}

/**
 * 判断新建活动的信息完整性
 */
async function actCreateValidator (ctx, next) {
    try {
        const { actTitle, actContent, actType, organizerAccount, teacherAccount, startTime, endTime } = ctx.request.body
        const imgList = ctx.request.files ? ctx.request.files.actImg : []
        if (!actTitle || !actContent || !actType.toString() || !organizerAccount || !teacherAccount || !startTime || !endTime) {
            // 缺少一个字段都不行
            // 信息不完整时，删除上传的图片
            imgList.forEach((item) => {
                fs.unlink(item.filepath, (err) => {
                    if (err) {
                        // 找不到旧图像路径
                        console.error('找不到该图片', err)
                    }
                })
            })
            console.error('创建失败，缺少必要字段', ctx.request.body)
            ctx.app.emit('error', formateError, ctx)
            return
        }
    } catch (error) {
        console.log(error)
    }
    await next()
}

/**
 * 上传活动图片时koa-body 图片上传配置
 */
const actImgKoaBody = koaBody({
    multipart: true,
    formidable: {
        uploadDir: path.join(__dirname, "../public/upload"),
        keepExtensions: true,
        filter: (part) => {
            // 判断图片的类型
            const fileTpyes = ['image/jpeg', 'image/png', 'image/jpg']
            if (!fileTpyes.includes(part.mimetype)) {
                // 图片是系统不支持的类型则返回错误注册失败
                console.error('不支持的图片类型', part.originalFilename)
                return false
            } else {
                return true
            }
        },
        onFileBegin: (name, file) => {
            // 获取上传文件的后缀
            // let ext = file.originalFilename.split('.')
            // 最终要保存到的文件夹目录（暂时使用name作为次级目录）
            let dir = ''
            dir = path.join(__dirname, `../public/upload/activity`)
            // 检查文件夹是否存在, 如果不存在则新建文件夹
            checkDirExist(dir)
            // 拼接存放地址
            file.filepath = `${dir}/${file.newFilename}`
        },
    },
    onError: (err, ctx) => {
        console.error(err)
    }
})


/**
 * 判断审批用户的权限
 */
async function judgeApprovalUserPwoer (ctx, next) {
    try {
        const { role, userAccount } = ctx.state.token
        const { actId } = ctx.request.body
        const { rows: actInfoRes } = await getActInfo({ act_id: actId })
        const actInfoDataVaulues = actInfoRes[0].dataValues
        // 如果该用户的角色不是[超级]管理员或者该用户的账号不是活动创建时指定的审批账号，则权限不足
        if (role !== 'super_admin' && role !== 'admin' && actInfoDataVaulues.teacher_account !== userAccount) {
            console.error('用户权限不足', role)
            ctx.app.emit('error', insufficientPermissionsError, ctx)
            return
        }
    } catch (error) {
        console.log(error)
    }
    await next()
}

/**
 * 判断活动是否已经经过审批
 */
async function actIsApproval (ctx, next) {
    try {
        const { actId } = ctx.request.body
        const { rows: actInfoRes } = await getActInfo({ act_id: actId })
        const actInfoDataVaulues = actInfoRes[0].dataValues
        if (actInfoDataVaulues.approval_status !== 0) {
            console.error('该活动已经审批，不要重复审批', actId)
            ctx.app.emit('error', actapprovedError, ctx)
            return
        }
    } catch (error) {
        console.log(error)
    }
    await next()
}

/**
 * 活动签到签退
 */
async function determineStartEndTime (ctx, next) {
    const { signTime, actId, userAccount } = ctx.request.body
    console.log(actId)
    const res = await getACtDetailById(actId)
    // 先判断活动是否已经开始，或结束
    if (Date.parse(signTime) >= Date.parse(res.start_time) && Date.parse(signTime) <= Date.parse(res.end_time)) {
        let isFirstSign = true
        // 先判断是签到还是签退 判断这个人有没有签到记录
        const serachChuangxinRes = await getChuangxinList({ act_id: actId, user_account: userAccount })
        if (serachChuangxinRes.length !== 0) {
            isFirstSign = false
        }
        // 1 为学业分
        const serachXueyeRes = await getXueyeList({ act_id: actId, user_account: userAccount })
        if (serachXueyeRes.length !== 0) {
            isFirstSign = false
        }
        // 2 为思想分
        const serachSixiangRes = await getSixiangList({ act_id: actId, user_account: userAccount })
        if (serachSixiangRes.length !== 0) {
            isFirstSign = false
        }
        // 3 为文体分
        const serachWentiRes = await getWentiList({ act_id: actId, user_account: userAccount })
        if (serachWentiRes.length !== 0) {
            isFirstSign = false
        }
        if (isFirstSign) {
            // 如果是签到，则判断开始时间（半个小时后）
            if (Date.parse(signTime) <= Date.parse(res.start_time) + 1200000) {
                ctx.state.isFirstSign = true
                await next()
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: false,
                    code: 20000,
                    message: '活动签到已结束',
                    data: {}
                }
            }
        } else {
            // 如果是签退，则判断结束时间（半个小时前）
            if (Date.parse(signTime) > Date.parse(res.start_time) + 1200000 && Date.parse(signTime) <= Date.parse(res.end_time) - 1200000) {
                ctx.status = 200
                ctx.body = {
                    hasOk: false,
                    code: 20000,
                    message: '还未到签退时间，请耐心等待',
                    data: {}
                }
            } else if (Date.parse(signTime) >= Date.parse(res.end_time) - 1200000) {
                ctx.state.isFirstSign = false
                await next()
            }
        }
    } else if (Date.parse(signTime) < Date.parse(res.start_time)) {
        ctx.status = 200
        ctx.body = {
            hasOk: false,
            code: 20000,
            message: '活动未开始',
            data: {}
        }
    } else if (Date.parse(signTime) > Date.parse(res.end_time)) {
        console.log(signTime)
        console.log(res.end_time)
        ctx.status = 200
        ctx.body = {
            hasOk: false,
            code: 20000,
            message: '活动已结束',
            data: {}
        }
    }
}

/**
 * 判断签到时间是否符合
 */
async function determineTime (ctx, next) {
    try {
        const { signTime, actId } = ctx.request.body
        const res = await getACtDetailById(actId)
        if (Date.parse(signTime) >= Date.parse(res.start_time) && Date.parse(signTime) <= Date.parse(res.end_time)) {
            await next()
        } else if (Date.parse(signTime) < Date.parse(res.start_time)) {
            ctx.status = 200
            ctx.body = {
                hasOk: false,
                code: 20000,
                message: '活动未开始',
                data: {}
            }
        } else if (Date.parse(signTime) > Date.parse(res.end_time)) {
            ctx.status = 200
            ctx.body = {
                hasOk: false,
                code: 20000,
                message: '活动已结束',
                data: {}
            }
        }
    } catch (error) {
        ctx.status = 500
        console.error(error)
    }
}

/**
 * 判断签到地点范围是否符合
 */
async function determineLoaction (ctx, next) {
    try {
        const { userLatitude, userLongitude, actId } = ctx.request.body
        const LoctionRes = await getActLoaction(actId)
        if (!LoctionRes) {
            ctx.status = 500
            return
        }
        let distance = getDistance(userLatitude * 1, userLongitude * 1, LoctionRes.latitude, LoctionRes.longitude)
        if (distance > 100) {
            ctx.status = 200
            ctx.body = {
                hasOk: false,
                code: 20000,
                message: '非签到范围内',
                data: distance
            }
            return
        }

        await next()
    } catch (error) {
        ctx.status = 500
        console.error(error)
    }
}

/**
 * 上传参赛文件
 */
const entryKoaBody = koaBody({
    multipart: true,
    formidable: {
        uploadDir: path.join(__dirname, "../public/upload"),
        keepExtensions: true,
        filter: (part) => {
            // 判断图片的类型
            return true
        },
        onFileBegin: (name, file) => {
            // 获取上传文件的后缀
            // let ext = file.originalFilename.split('.')
            // 最终要保存到的文件夹目录（暂时使用name作为次级目录）
            let dir = ''
            dir = path.join(__dirname, `../public/upload/${name}`)
            // 检查文件夹是否存在, 如果不存在则新建文件夹
            checkDirExist(dir)
            // 拼接存放地址
            file.filepath = `${dir}/${file.newFilename}`
        },
    },
    onError: (err, ctx) => {
        console.error(err)
    }
})

/**
 * 文件上传之后处理存入地址的格式
 */
async function uploadEntryFormat (ctx, next) {
    // 判断是否有符合条件的头像
    const files = ctx.request.files
    if (!files || Object.keys(files).length === 0) {
        console.error('文件上传失败', files)
        ctx.app.emit('error', avatarError, ctx)
        return
    }
    // 更改头像存入数据库的路径
    const newPath = 'entry/' + path.basename(files.entry.filepath)
    const entry_path = newPath
    ctx.state.entry_path = entry_path
    await next()
}

/**
 * 获取活动的加分分数和类别
 */
async function getSignScoreTypeAndScore (ctx, next) {
    const { actId } = ctx.request.body
    const res = await getActSignScoreListByActId(actId)
    let resList = []
    res.forEach(item => {
        let resObj = {}
        resObj.score = item.score
        resObj.score_type = item.score_type
        resList.push(resObj)
    })
    ctx.state.scoreSignList = resList
    await next()
}

/**
 * 判断加分文件审核时间
 */
async function determineScoreApprovalTime (ctx, next) {
    const { actId } = ctx.request.body
    const res = await getACtDetailById(actId)
    const endTime = Date.parse(res.end_time)
    const nowTime = Date.parse(new Date())
    if (nowTime < endTime) {
        ctx.status = 200
        ctx.body = {
            hasOk: false,
            code: 20000,
            message: '活动还未结束，请等待活动结束再进行审批',
            data: ''
        }
        return
    }
    await next()
}

module.exports = {
    actIdIsExist,
    judgeCreateUserPwoer,
    actCreateValidator,
    actImgKoaBody,
    judgeApprovalUserPwoer,
    actIsApproval,
    determineTime,
    determineLoaction,
    entryKoaBody,
    uploadEntryFormat,
    getSignScoreTypeAndScore,
    determineScoreApprovalTime,
    determineStartEndTime,
}